using System;

using Microsoft.Cci;
using Microsoft.FxCop.Sdk;
using Microsoft.FxCop.Sdk.Introspection;

namespace Tyng.Rules
{
	public abstract class DoNotInstantiateTypeBase<T> : MethodInstructionRuleBase<T>
        where T : DoNotInstantiateTypeBase<T>
	{
		private TypeNodeList _doNotInstantiate;

		protected DoNotInstantiateTypeBase(params Type[] types) : this(CciUtilities.GetTypeNodeList(types)) {}

		protected DoNotInstantiateTypeBase(params TypeNode[] types) : this(new TypeNodeList(types)) {}

		protected DoNotInstantiateTypeBase(TypeNodeList types) : base(OpCode.Newobj)
		{
			if(types == null)
				throw new ArgumentNullException("types");

			if(types.Length == 0)
				throw new ArgumentException("At least one type is required", "types");


			_doNotInstantiate = types;
		}	

		protected override void CheckInstruction(Instruction instruction, Method method)
		{
			if(IsDoNotInstantiate(instruction))
			{
				Problems.Add(new Problem(GetResolution(GetResolutionParameters(instruction, method)), instruction));
			}
		}

		private bool IsDoNotInstantiate(Instruction instruction)
		{
			InstanceInitializer constructor = instruction.Value as InstanceInitializer;

			if(constructor == null)
				return false;

			for(int i = 0; i < _doNotInstantiate.Length; i++)
			{
				if(constructor.DeclaringType.IsAssignableTo(_doNotInstantiate[i]))
						return true;
			}

			return false;
		}

		protected virtual string[] GetResolutionParameters(Instruction instruction, Method method)
		{
			return new string[0];
		}

		
	}
}
